﻿using System;
using System.Data;
using System.Xml;

namespace ZYCommon
{
    

    public class XMLHttpCommand : IDbCommand, IDisposable
    {
        internal bool bolCancel = false;
        private const string c_NullFlag = "[NULL]";
        public XMLHttpDBExecutingHandler ExecuteEvent = null;
        private CommandBehavior intCmdBehavior = CommandBehavior.Default;
        private int intCommandTimeout = 0;
        private System.Data.CommandType intCommandType = System.Data.CommandType.Text;
        private int intExecuteState = 0;
        private int intExecuteType = 0;
        private UpdateRowSource intUpdatedRowSource = UpdateRowSource.Both;
        private XMLHttpConnection myConnection = null;
        private XMLHttpParameterCollection myParameters = new XMLHttpParameterCollection();
        private XmlDocument myXMLDoc = new XmlDocument();
        private string strCommandText = null;
        private string strHttpMethod = "POST";

        public void Cancel()
        {
            this.bolCancel = true;
        }

        public IDbDataParameter CreateParameter()
        {
            return new XMLHttpParameter();
        }

        public void Dispose()
        {
        }

        private bool ExecuteCommand()
        {
            this.myXMLDoc.LoadXml("<xmlhttpconnection />");
            this.ToXML(this.myXMLDoc.DocumentElement);
            string outerXml = this.myXMLDoc.DocumentElement.OuterXml;
            ZYErrorReport.Instance.DebugPrint("发送数据:" + outerXml);
            byte[] bytes = this.myConnection.SendEncod.GetBytes(outerXml);
            byte[] buffer2 = this.myConnection.PostData(bytes, this);
            if (this.bolCancel)
            {
                return false;
            }
            if (buffer2 == null)
            {
                throw new Exception("远程WEB服务器未返回任何数据");
            }
            this.intExecuteState = 3;
            string xml = new string(this.myConnection.ReserveEncod.GetChars(buffer2));
            xml = xml.Trim();
            if (this.myXMLDoc == null)
            {
                this.myXMLDoc = new XmlDocument();
            }
            this.myXMLDoc.PreserveWhitespace = true;
            try
            {
                this.myXMLDoc.LoadXml(xml);
            }
            catch (Exception exception)
            {
                throw new Exception("远程Web数据库获得的数据格式错误!\r\n返回的数据为:" + xml, exception);
            }
            this.intExecuteState = 0;
            if (this.myXMLDoc.DocumentElement.GetAttribute("error") == "1")
            {
                throw new Exception("远程WEB数据库操作错误\r\n" + StringCommon.ClearBlankLine(this.myXMLDoc.DocumentElement.InnerText));
            }
            return true;
        }

        public int ExecuteNonQuery()
        {
            this.intExecuteType = 1;
            if (this.ExecuteCommand())
            {
                return Convert.ToInt32(this.myXMLDoc.DocumentElement.InnerText);
            }
            return -1;
        }

        public IDataReader ExecuteReader(CommandBehavior behavior)
        {
            this.intCmdBehavior = behavior;
            this.intExecuteType = 0;
            if (this.ExecuteCommand())
            {
                XMLHttpReader reader = new XMLHttpReader();
                reader.FromXML(this.myXMLDoc.DocumentElement);
                return reader;
            }
            return null;
        }

        public object ExecuteScalar()
        {
            return null;
        }

        public string ExecuteString()
        {
            if (this.ExecuteCommand())
            {
                return this.myXMLDoc.DocumentElement.InnerText;
            }
            return null;
        }

        public bool FromXML(XmlElement myElement)
        {
            if (myElement != null)
            {
                this.intExecuteType = StringCommon.ToInt32Value(myElement.GetAttribute("type"), 0);
                this.strCommandText = myElement.GetAttribute("text");
                this.myParameters.Clear();
                foreach (XmlNode node in myElement.ChildNodes)
                {
                    if (node.Name == "param")
                    {
                        XmlElement element = node as XmlElement;
                        XMLHttpParameter parameter = new XMLHttpParameter();
                        parameter.ParameterName = element.GetAttribute("name");
                        parameter.LongText = element.HasAttribute("longtext");
                        parameter.Value = element.InnerText;
                        this.myParameters.Add(parameter);
                    }
                }
            }
            return true;
        }

        private void myConnection_OnCancelPostData(object sender, EventArgs e)
        {
            this.bolCancel = true;
        }

        public void Prepare()
        {
        }

        IDataReader IDbCommand.ExecuteReader()
        {
            this.intExecuteType = 0;
            if (this.ExecuteCommand())
            {
                XMLHttpReader reader = new XMLHttpReader();
                reader.FromXML(this.myXMLDoc.DocumentElement);
                return reader;
            }
            return null;
        }

        public bool ToXML(XmlElement myElement)
        {
            if (myElement != null)
            {
                myElement.SetAttribute("text", this.strCommandText);
                myElement.SetAttribute("type", this.intExecuteType.ToString());
                myElement.SetAttribute("user", this.myConnection.UserName);
                myElement.SetAttribute("pwd", this.myConnection.Password);
                foreach (XMLHttpParameter parameter in this.myParameters)
                {
                    XmlElement newChild = myElement.OwnerDocument.CreateElement("param");
                    myElement.AppendChild(newChild);
                    newChild.SetAttribute("name", parameter.ParameterName);
                    if (parameter.LongText)
                    {
                        newChild.SetAttribute("longtext", "1");
                    }
                    newChild.InnerText = (parameter.Value == null) ? "[NULL]" : parameter.Value.ToString();
                }
            }
            return true;
        }

        public string CommandText
        {
            get
            {
                return this.strCommandText;
            }
            set
            {
                this.strCommandText = value;
            }
        }

        public int CommandTimeout
        {
            get
            {
                return this.intCommandTimeout;
            }
            set
            {
                this.intCommandTimeout = value;
            }
        }

        public System.Data.CommandType CommandType
        {
            get
            {
                return this.intCommandType;
            }
            set
            {
                this.intCommandType = value;
            }
        }

        public IDbConnection Connection
        {
            get
            {
                return this.myConnection;
            }
            set
            {
                this.myConnection = (XMLHttpConnection) value;
                this.myConnection.OnCancelPostData += new EventHandler(this.myConnection_OnCancelPostData);
            }
        }

        public int ExecuteState
        {
            get
            {
                return this.intExecuteState;
            }
        }

        public string HttpMethod
        {
            get
            {
                return this.strHttpMethod;
            }
            set
            {
                this.strHttpMethod = value;
            }
        }

        public IDataParameterCollection Parameters
        {
            get
            {
                return this.myParameters;
            }
        }

        public IDbTransaction Transaction
        {
            get
            {
                return null;
            }
            set
            {
            }
        }

        public UpdateRowSource UpdatedRowSource
        {
            get
            {
                return this.intUpdatedRowSource;
            }
            set
            {
                this.intUpdatedRowSource = value;
            }
        }
    }
}

